//------------------------------------------------------------------------------
// <copyright file="NativeBuffer.h" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#pragma once

#include <wrl.h>
#include <wrl/implements.h>
#include <windows.storage.streams.h>
#include <robuffer.h>
#include <vector>

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server
{

	/// <summary>
	/// A class to wrap a pointer to native data into a IBuffer and IBufferByteAccess.
	/// </summary>
	/// <remarks>
	/// This class was retrieved from http://stackoverflow.com/a/12125386/2611613
	/// </remarks>
	class NativeBuffer : 
		public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>,
		ABI::Windows::Storage::Streams::IBuffer,
		Windows::Storage::Streams::IBufferByteAccess>
	{
	public:
		virtual ~NativeBuffer()
		{
		}

		STDMETHODIMP RuntimeClassInitialize(byte *buffer, UINT totalSize)
		{
			m_length = totalSize;
			m_buffer = buffer;

			return S_OK;
		}

		STDMETHODIMP Buffer(__RPC__out byte **value)
		{
			*value = m_buffer;

			return S_OK;
		}

		STDMETHODIMP get_Capacity(__RPC__out UINT32 *value)
		{
			*value = m_length;

			return S_OK;
		}

		STDMETHODIMP get_Length(__RPC__out UINT32 *value)
		{
			*value = m_length;

			return S_OK;
		}

		STDMETHODIMP put_Length(UINT32 value)
		{
			m_length = value;

			return S_OK;
		}

	/// <summary>
	/// Wraps a pointer to a native buffer in a IBuffer.
	/// </summary>
		/// <param name="lpBuffer">A pointer to a native buffer.</param>
		/// <param name="nNumberOfBytes">The length of the native buffer.</param>
		static Windows::Storage::Streams::IBuffer ^CreateNativeBuffer(LPVOID lpBuffer, DWORD nNumberOfBytes)
	{
		Microsoft::WRL::ComPtr<NativeBuffer> nativeBuffer;
		Microsoft::WRL::Details::MakeAndInitialize<NativeBuffer>(&nativeBuffer, (unsigned __int8 *)lpBuffer, nNumberOfBytes);
		auto iinspectable = (IInspectable *)reinterpret_cast<IInspectable *>(nativeBuffer.Get());
		Windows::Storage::Streams::IBuffer ^buffer = reinterpret_cast<Windows::Storage::Streams::IBuffer ^>(iinspectable);

		return buffer;
	}

	private:
		UINT32 m_length;
		byte *m_buffer;
	};

}}}}}